import pygame
import random
from pygame.sprite import Group
from brick import GeneticBrick, FlockingBrick, Brick


class BrickWall:
    def __init__(self, game, level_type):
        """
        初始化砖块墙。
        level_type: 关卡类型（"normal"、"genetic"、"flocking"）。
        """
        self.config = game.config
        self.level_type = level_type
        self.bricks = Group()  # 存储所有砖块
        self.generate_bricks()  # 生成砖块

    def generate_bricks(self):
        """
        根据关卡类型生成砖块。
        """
        if self.level_type == "genetic":
            self._generate_genetic_bricks()
        elif self.level_type == "flocking":
            self._generate_flocking_bricks()
        else:
            self._generate_normal_bricks()

    def _generate_normal_bricks(self):
        """
        生成普通关卡的砖块。
        """
        for row in range(self.config.brick_rows):
            for col in range(self.config.brick_cols):
                x = col * (self.config.brick_width + self.config.brick_padding) + 30
                y = row * (self.config.brick_height + self.config.brick_padding) + 50
                brick = Brick(x, y, (0, 255, 0))  # 绿色砖块
                self.bricks.add(brick)

    def _generate_genetic_bricks(self):
        """
        生成遗传算法关卡的砖块。
        """
        # 1. 生成初始种群
        population = [self._create_genetic_pattern() for _ in range(10)]

        # 2. 遗传算法优化
        best_pattern = self._genetic_algorithm(population)

        # 3. 应用最优模式生成砖块
        self._apply_genetic_pattern(best_pattern)

    def _create_genetic_pattern(self):
        """
        生成一个随机的遗传模式。
        :return: 布尔数组，True 表示生成砖块。
        """
        return [random.random() < 0.6 for _ in range(self.config.brick_cols)]

    def _genetic_algorithm(self, population):
        """
        遗传算法优化过程。
        :param population: 初始种群。
        :return: 最优模式。
        """
        generations = 5
        for _ in range(generations):
            # 评估适应度
            scored = [(self._fitness(pattern), pattern) for pattern in population]
            scored.sort(reverse=True, key=lambda x: x[0])

            # 选择前50%
            selected = [pattern for _, pattern in scored[:len(population) // 2]]

            # 交叉和变异
            new_generation = []
            while len(new_generation) < len(population):
                parent1, parent2 = random.choices(selected, k=2)
                child = self._crossover(parent1, parent2)
                child = self._mutate(child)
                new_generation.append(child)

            population = new_generation

        # 返回最优模式
        return max(population, key=lambda p: self._fitness(p))

    @staticmethod
    def _fitness(pattern):
        """
        计算模式的适应度。
        :param pattern: 遗传模式。
        :return: 适应度值。
        """
        # 适应度函数：平衡砖块密度和分布复杂性
        density = sum(pattern) / len(pattern)  # 砖块密度
        complexity = sum(abs(i - j) for i, j in zip(pattern, pattern[1:]))  # 分布复杂性
        return density * 0.7 + complexity * 0.3

    @staticmethod
    def _crossover(p1, p2):
        """
        单点交叉。
        :param p1: 父代1。
        :param p2: 父代2。
        :return: 子代。
        """
        point = random.randint(1, len(p1) - 1)
        return p1[:point] + p2[point:]

    @staticmethod
    def _mutate(pattern):
        """
        概率变异。
        :param pattern: 原始模式。
        :return: 变异后的模式。
        """
        return [not gene if random.random() < 0.1 else gene for gene in pattern]

    def _apply_genetic_pattern(self, pattern):
        """
        将遗传算法生成的最优模式应用到砖块生成。
        :param pattern: 布尔数组，True 表示生成砖块。
        """
        for row in range(self.config.brick_rows):
            for col, valid in enumerate(pattern):
                if valid:
                    x = col * (self.config.brick_width + self.config.brick_padding) + 30
                    y = row * (self.config.brick_height + self.config.brick_padding) + 50
                    brick = GeneticBrick(x, y)  # 生成遗传算法砖块
                    self.bricks.add(brick)  # 添加到砖块组
            # 模式向下移位（模拟基因传递）
            pattern = pattern[-1:] + pattern[:-1]

    def _generate_flocking_bricks(self):
        """
        生成鸟群算法关卡的砖块。
        """
        for _ in range(20):  # 生成20个动态砖块
            x = random.randint(0, self.config.screen_width - self.config.brick_width)
            y = random.randint(50, 200)
            brick = FlockingBrick(x, y)
            self.bricks.add(brick)

    def update(self):
        """
        更新砖块状态（仅对动态砖块有效）。
        """
        if self.level_type == "flocking":
            # 更新所有鸟群砖块
            for brick in self.bricks:
                brick.update(self.bricks)
        elif self.level_type == "genetic":
            # 更新所有遗传砖块
            self.bricks.update()

    def check_collision(self, ball):
        collisions = pygame.sprite.spritecollide(ball, self.bricks, True)
        if collisions:
            # 获取第一个碰撞的砖块
            brick = collisions[0]

            # 计算碰撞方向
            dx = ball.rect.centerx - brick.rect.centerx
            dy = ball.rect.centery - brick.rect.centery

            # 根据主要碰撞方向调整速度
            if abs(dx) > abs(dy):  # 水平碰撞
                ball.velocity.x *= -1
            else:  # 垂直碰撞
                ball.velocity.y *= -1

            return len(collisions)
        return 0

    def is_empty(self):
        """
        检查砖块墙是否为空。
        :return: 如果砖块墙为空，返回 True；否则返回 False。
        """
        return len(self.bricks) == 0

    def reset(self):
        """
        重置砖块墙。
        """
        self.bricks.empty()  # 清空所有砖块
        self.generate_bricks()  # 重新生成砖块
